package com.chenyue.cm.test;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableFill;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import com.chenyue.cm.bean.CodeMakerBean;
import com.chenyue.cm.common.utils.Freemarker;
import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.*;
import org.mybatis.generator.exception.InvalidConfigurationException;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.io.IOException;
import java.sql.SQLException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 自定义封装 mybatis 逆向工程
 * ***********************************************
 * Created by chenyue on 2019/3/21.
 */
public class CmDomainGenerator {


    private static final String DriverClass = "com.mysql.jdbc.Driver";
    //	private static final String  ConnectionURL = "jdbc:mysql://CHENYUE-PC:3307/cm-lc";
//	private static final String  UserId = "root";
//	private static final String  Password = "123456";
    private static final String ConnectionURL = "jdbc:mysql://180.76.114.186:3306/guanai-medical";
    private static final String UserId = "root";
    private static final String Password = "longcaijava@123";


    private static final String basePathJava = "src/main/java/";
    private static final String basePathResource = "src/main/resources/";

    private static final String projectPathDomain = "/Users/libingxing/Desktop/git/guanai-medical/guanni-live/";
    private static final String projectPathAdmin = "/Users/libingxing/Desktop/git/guanai-medical/guanni-live/";

    private static final String TargetPackageString = "com.chenyue.cm";
    private static final String TargetPackagPath = "com/chenyue/cm/";

//	private static final String  TargetPackagPath2 = "com/master/";//临时使用


    private static final String outFilePathDomain = projectPathDomain + basePathJava + TargetPackagPath;
    private static final String outFilePathMapper = projectPathDomain + basePathJava + TargetPackagPath;

    private static final String contextPath = "/Users/libingxing/Desktop/git/guanai-medical/" + "guanai-modules-codemaker/" + basePathResource;


    public static void main(String[] args) throws Exception {

        /* A. 系统模块-----system*/
        String[] tables = new String[]{
                "sys_config", "sys_dept", "sys_dic_code", "sys_dic_value", "sys_log",
                "sys_menus", "sys_role_menus", "sys_roles", "sys_users", "sys_users_role"};
        //dddddo(tables,"system");


        //门户官网模块
        String[] tables_ = new String[]{"live_broadcast"};
        dddddo(tables_, "live");


        /* B. 微信公众号模块-----wechat*/
		/*String[] tables  = new String[]{ "wechat_menu", "wechat_reply","wechat_material"};
		dddddo(tables,"wechat");*/


		/*String[] tables  = new String[]{ "cms_art_content", "cms_art_type","cms_comment"};
		dddddo(tables,"cms");*/



		/*String[] tables  = new String[]{  "mall_promote_rule" , "mall_g_promote_rela" ,"mall_rela_g_spec"  , "mall_rela_g_prom"  };
		dddddo(tables,"mall");*/

    }

    /**
     * @param tables  String[] 表名数组
     * @param moudule 模块名称
     * @throws Exception
     */
    private static void dddddo(String[] tables, String moudule) throws Exception {

        /*mybatis生成*/
        /*mybatisPlus生成*/
        doMyBatis(tables, moudule);
        doMyBatisPlus(tables, moudule);

        //业务层生成
//        doYewuJava(tables, moudule);
//		doYewuPage(tables,moudule);
    }

    /**
     * @param tableString
     * @param moudule
     * @throws Exception
     */
    private static void doYewuJava(String[] tableString, String moudule) throws Exception {
        //4freemarker 生成业务层文件
        for (int i = 0; i < tableString.length; i++) {
            String tablename = tableString[i];
            Map<String, Object> paramMap = new HashMap<String, Object>();
            paramMap.put("moudule", moudule);//所属父模块
            paramMap.put("targetPackageString", TargetPackageString);//所属父模块  包名前缀
            paramMap.put("describe", tablename);//模块描述
            CodeMakerBean cmb = new CodeMakerBean(tablename, paramMap, new ArrayList<Map<String, Object>>());
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("vo", cmb);
//            String pathSrcString = projectPathAdmin + basePathJava + TargetPackagPath +"moudules"+moudule;
            String pathSrcString = projectPathAdmin + basePathJava + TargetPackagPath + moudule;
            System.out.println(pathSrcString);
            Freemarker.printFile("controller.ftl", dataMap, pathSrcString + "/controller/" + underlineToCamel("_" + tablename.replace("crm_", "")) + "Controller.java", contextPath);
            Freemarker.printFile("service.ftl", dataMap, pathSrcString + "/service/" + underlineToCamel("_" + tablename.replace("crm_", "")) + "Service.java", contextPath);
            Freemarker.printFile("serviceImpl.ftl", dataMap, pathSrcString + "/service/" + "impl/" + underlineToCamel("_" + tablename.replace("crm_", "")) + "ServiceImpl.java", contextPath);
        }
    }

    /**
     * @param tableString
     * @param moudule
     * @throws Exception
     */
    private static void doYewuPage(String[] tableString, String moudule) throws Exception {
        //5 freemarker 生成视图层文件
        for (int i = 0; i < tableString.length; i++) {
            String tablename = tableString[i];
            Map<String, Object> paramMap = new HashMap<String, Object>();
            paramMap.put("moudule", moudule);//所属父模块
            paramMap.put("targetPackageString", TargetPackageString);//所属父模块  包名前缀
            paramMap.put("describe", tablename);//模块描述
            CodeMakerBean cmb = new CodeMakerBean(tablename.replace("crm_", ""), paramMap, new ArrayList<Map<String, Object>>());
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("vo", cmb);
            String pathHtmlString = projectPathAdmin + basePathResource + "/templates/" + moudule;
            System.out.println(pathHtmlString);
            Freemarker.printFile("list.ftl", dataMap, pathHtmlString + "/" + underlineToCamel(tablename.replace("crm_", "")).toLowerCase() + "/" + underlineToCamel(tablename.replace("crm_", "")) + "List.html", contextPath);
            Freemarker.printFile("form.ftl", dataMap, pathHtmlString + "/" + underlineToCamel(tablename.replace("crm_", "")).toLowerCase() + "/" + underlineToCamel(tablename.replace("crm_", "")) + "Form.html", contextPath);
        }
    }

    /**
     * @param tableString
     * @param moudule
     * @throws Exception
     */
    private static void doMyBatisPlus(String[] tableString, String moudule) throws Exception {

        //1 删除原来的domain
        for (int i = 0; i < tableString.length; i++) {
            String filePath = outFilePathDomain + moudule + "/domain/" + underlineToCamel("_" + tableString[i]) + ".java";
            System.out.println(filePath);
            new File(filePath).delete();
            System.out.println(tableString[i]);
        }

        //2生成plus对应的domain
        doGenerator(projectPathDomain + basePathJava, tableString, TargetPackageString + "." + moudule);

        //3freemarker 生成mapper文件
        for (int i = 0; i < tableString.length; i++) {
            String tablename = tableString[i];
            Map<String, Object> paramMap = new HashMap<String, Object>();
            paramMap.put("moudule", moudule);//所属父模块
            paramMap.put("describe", "");//模块描述
            CodeMakerBean cmb = new CodeMakerBean(tablename, paramMap, new ArrayList<Map<String, Object>>());
            System.err.println(JSON.toJSONString(cmb));
            Map<String, Object> dataMap = new HashMap<String, Object>();
            dataMap.put("vo", cmb);
            Freemarker.printFile("mapper.ftl", dataMap, outFilePathMapper + moudule + "/dao/" + underlineToCamel("_" + tablename) + "Mapper.java", contextPath);
        }
    }

    private static void doGenerator(String outFilePath, String[] tableString, String packageString) {

        AutoGenerator mpg = new AutoGenerator();
        mpg.setTemplateEngine(new FreemarkerTemplateEngine());

        // 全局配置
        GlobalConfig gc = new GlobalConfig()
                // 打开文件
                .setOpen(false)
                // 文件覆盖
                .setFileOverride(true)
                // 开启activeRecord模式
                .setActiveRecord(true)
                // XML ResultMap: mapper.xml生成查询映射结果
                .setBaseResultMap(true)
                // XML ColumnList: mapper.xml生成查询结果列
                .setBaseColumnList(false)
                // XML 二级缓存
                .setEnableCache(false)
                // 输出目录
                .setOutputDir(outFilePath)
                // 主键自增
                .setIdType(IdType.ASSIGN_UUID)
                // 时间类型
                .setDateType(DateType.ONLY_DATE)
                // 作者
                .setAuthor("Lbx")
                // 开启swagger
                .setSwagger2(true);

        mpg.setGlobalConfig(gc);

        // 数据源配置
        mpg.setDataSource(getDsc());

        // 策略配置
        StrategyConfig strategy = new StrategyConfig()
                // 表名生成策略：下划线连转驼峰
                .setNaming(NamingStrategy.underline_to_camel)
                // 表字段生成策略：下划线连转驼峰
                .setColumnNaming(NamingStrategy.underline_to_camel)
                // 需要生成的表
                .setInclude(tableString)
                // 生成controller
//                .setRestControllerStyle(true)
                // 去除表前缀
//                .setTablePrefix("jd", "sys")
                // controller映射地址：驼峰转连字符
                .setControllerMappingHyphenStyle(false)
                // 是否启用builder 模式
//                .setEntityBuilderModel(true)
                // 是否为lombok模型; 需要lombok依赖
                .setEntityLombokModel(true)
                // restController 风格
//                .setRestControllerStyle(true)
                // 生成实体类字段注解
                .setEntityTableFieldAnnotationEnable(true)
                // 乐观锁、逻辑删除、表填充
//                .setVersionFieldName("version")
//                .setLogicDeleteFieldName("deleted")
                .setTableFillList(Arrays.asList(
                        new TableFill("et", FieldFill.UPDATE),
                        new TableFill("ct", FieldFill.INSERT)
                ))
                // 生成类的时候排除的字符串
                .setSuperEntityColumns(
                        ""
                );
        mpg.setStrategy(strategy);

        // 包配置
        PackageConfig pc = new PackageConfig();
        pc.setParent(packageString);
        pc.setEntity("domain");
        pc.setMapper("dao");
        pc.setController("controller");
        pc.setService("service");
        mpg.setPackageInfo(pc);

        // 关闭默认 xml 生成，调整生成 至 根目录
        TemplateConfig tc = new TemplateConfig();
        tc.setController(null);
        tc.setService(null);
        tc.setMapper(null);
        tc.setServiceImpl(null);
        tc.setXml(null);
        mpg.setTemplate(tc);

        // 执行生成
        mpg.execute();

    }


    /**
     * 下划线格式字符串转换为驼峰格式字符串
     *
     * @param param
     * @return
     */
    public static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        StringBuilder sb = new StringBuilder(param);
        Matcher mc = Pattern.compile("_").matcher(param);
        int i = 0;
        while (mc.find()) {
            int position = mc.end() - (i++);
            sb.replace(position - 1, position + 1, sb.substring(position, position + 1).toUpperCase());
        }
        return sb.toString();
    }


    //1111
    private static void doMyBatis(String[] tables, String moudule) {
        try {
            /* 配置xml配置项 */
            List<String> warnings = new ArrayList<String>();
            boolean overwrite = true;
            Configuration config = new Configuration();
            Context context = new Context(ModelType.CONDITIONAL);
            context.setTargetRuntime("MyBatis3");
            context.setId("defaultContext");
            // 自动识别数据库关键字，默认false，如果设置为true，
            // 根据SqlReservedWords中定义的关键字列表；一般保留默认值，遇到数据库关键字（Java关键字），
            // 使用columnOverride覆盖
            context.addProperty("autoDelimitKeywords", "true");
            // 生成的Java文件的编码
            context.addProperty("javaFileEncoding", "utf-8");
            context.addProperty("beginningDelimiter", "`");
            context.addProperty("endingDelimiter", "`");
            // 格式化java代码
            context.addProperty("javaFormatter", "org.mybatis.generator.api.dom.DefaultJavaFormatter");
            // 格式化xml代码
            context.addProperty("xmlFormatter", "org.mybatis.generator.api.dom.DefaultXmlFormatter");

            // 格式化信息
            PluginConfiguration pluginConfiguration = new PluginConfiguration();
            pluginConfiguration.setConfigurationType("org.mybatis.generator.plugins.SerializablePlugin");
            pluginConfiguration.setConfigurationType("org.mybatis.generator.plugins.ToStringPlugin");
            context.addPluginConfiguration(pluginConfiguration);

            // 设置是否生成注释
            CommentGeneratorConfiguration commentGeneratorConfiguration = new CommentGeneratorConfiguration();
            commentGeneratorConfiguration.addProperty("suppressAllComments", "true");
            commentGeneratorConfiguration.addProperty("suppressDate", "true");
            context.setCommentGeneratorConfiguration(commentGeneratorConfiguration);

            // 设置连接数据库
            JDBCConnectionConfiguration jdbcConnectionConfiguration = new JDBCConnectionConfiguration();
            jdbcConnectionConfiguration.setDriverClass(DriverClass);
            jdbcConnectionConfiguration.setConnectionURL(ConnectionURL);
            jdbcConnectionConfiguration.setUserId(UserId);
            jdbcConnectionConfiguration.setPassword(Password);
//			jdbcConnectionConfiguration.setConnectionURL("jdbc:mysql://CHENYUE-PC:3307/space");
//			jdbcConnectionConfiguration.setUserId("root");
//			jdbcConnectionConfiguration.setPassword("123456");
            context.setJdbcConnectionConfiguration(jdbcConnectionConfiguration);

            JavaTypeResolverConfiguration javaTypeResolverConfiguration = new JavaTypeResolverConfiguration();
            // 是否使用bigDecimal， false可自动转化以下类型（Long, Integer, Short, etc.）
            javaTypeResolverConfiguration.addProperty("forceBigDecimals", "false");
            context.setJavaTypeResolverConfiguration(javaTypeResolverConfiguration);

            // 生成实体类的地址
            JavaModelGeneratorConfiguration javaModelGeneratorConfiguration = new JavaModelGeneratorConfiguration();
            javaModelGeneratorConfiguration.setTargetPackage(TargetPackageString + "." + moudule + ".domain");
            javaModelGeneratorConfiguration.setTargetProject(projectPathDomain + basePathJava);
            javaModelGeneratorConfiguration.addProperty("enableSubPackages", "false");
            javaModelGeneratorConfiguration.addProperty("trimStrings", "true");
            context.setJavaModelGeneratorConfiguration(javaModelGeneratorConfiguration);

            // 生成的xml的地址
            SqlMapGeneratorConfiguration sqlMapGeneratorConfiguration = new SqlMapGeneratorConfiguration();
            sqlMapGeneratorConfiguration.setTargetProject(projectPathDomain + basePathResource);
            sqlMapGeneratorConfiguration.setTargetPackage("mybatis." + moudule);
            sqlMapGeneratorConfiguration.addProperty("enableSubPackages", "false");
            context.setSqlMapGeneratorConfiguration(sqlMapGeneratorConfiguration);

            // 生成mapxml对应client，也就是接口dao
            String TargetPackageDao = TargetPackageString + "." + moudule + ".dao";
            JavaClientGeneratorConfiguration javaClientGeneratorConfiguration = new JavaClientGeneratorConfiguration();
            javaClientGeneratorConfiguration.setTargetPackage(TargetPackageDao);
            javaClientGeneratorConfiguration.setTargetProject(projectPathDomain + basePathJava);
            javaClientGeneratorConfiguration.setConfigurationType("XMLMAPPER");
            javaClientGeneratorConfiguration.addProperty("enableSubPackages", "false");
            context.setJavaClientGeneratorConfiguration(javaClientGeneratorConfiguration);

            //table 表 设置
            for (String tableString : tables) {
                TableConfiguration tableConfiguration = getTableConfiguration(context, tableString);
                context.addTableConfiguration(tableConfiguration);
            }

            config.addContext(context);

            DefaultShellCallback callback = new DefaultShellCallback(overwrite);
            MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
            try {
                myBatisGenerator.generate(null);
            } catch (SQLException | IOException | InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        } catch (InvalidConfigurationException e) {
            e.printStackTrace();
        }

    }

    /**
     * 获取表名配置
     *
     * @param context
     * @param tbName
     * @return
     */
    private static TableConfiguration getTableConfiguration(Context context, String tbName) {
        //table  表 设置
        TableConfiguration tableConfiguration = new TableConfiguration(context);
        tableConfiguration.setTableName(tbName);
        tableConfiguration.setInsertStatementEnabled(false);//不生成insert sql
        tableConfiguration.setCountByExampleStatementEnabled(true);
        tableConfiguration.setUpdateByExampleStatementEnabled(true);
        tableConfiguration.setDeleteByExampleStatementEnabled(true);
        GeneratedKey generatedKey = new GeneratedKey("id", "MySql", true, null);
        tableConfiguration.setGeneratedKey(generatedKey);
        //context.addTableConfiguration(tableConfiguration);
        return tableConfiguration;
    }


    /**
     * 获取数据源信息
     *
     * @return DataSourceConfig
     */
    private static DataSourceConfig getDsc() {
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        //设置类型转换，不好使了
        dsc.setTypeConvert(new MySqlTypeConvertCustom());
        dsc.setDriverName(DriverClass);
        dsc.setUrl(ConnectionURL);
        dsc.setUsername(UserId);
        dsc.setPassword(Password);
        return dsc;
    }

    /**
     * 自定义类型转换
     */
    static class MySqlTypeConvertCustom extends MySqlTypeConvert implements ITypeConvert {
        @Override
        public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
            String t = fieldType.toLowerCase();
            if (t.contains("tinyint(1)")) {
                return DbColumnType.INTEGER;
            }
            if (t.contains("timestamp(0)")) {
                return DbColumnType.DATE;
            }
            return super.processTypeConvert(globalConfig, fieldType);
        }
    }


}
